/*****************************************************************************************************************
* File:SystemC.java
*
* Description:
*
* This class contains the entry point for System C, the main method which instantiates the filters 
* required for the system to run. It calls the connect method from FilterFramework2 to connect
* the ports of the filters together. It is used to set the parameters and to structure the pipe
* and filter system. Once the entire system is set up, a thread is started for each of the filters
*
* Parameters: 		Source File1 name, Source File2 name
*
*@author Team 10
*
******************************************************************************************************************/
public class SystemC extends SystemSuperClass
{
   public static void main( String argv[])
   {
	    
		   String filename1 = null;
		   String filename2 = null;
		   try
		   {
		   //Stores the names of the two input files in filename1 and filename2
		   filename1 = argv[0];
		   filename2 = argv[1];
		   
		   } 	catch (ArrayIndexOutOfBoundsException e){
				System.out.println("Correct Usage: java SystemC <sourcefile1> <sourcefile2>");
				System.exit(1);
			}
	    
		   
		 //This static method call determines the frame length to handle the case
		 //when different files have varying frame lengths
		   
		   determineFrameLength(filename1); //We use only one of the files to determine the frame length
		   									//since it has been clarified that both the files will have the same frame length
	   
	   /****************************************************************************
	   * Here we instantiate the filters needed for System C
	   ****************************************************************************/
		   
	    SourceFilter source1 = new SourceFilter(filename1); //Filter that reads source file 1
	    SourceFilter source2 = new SourceFilter(filename2); //Filter that reads source file 2
	    
	    SortFilter sort1 = new SortFilter();	//Filter that sorts the incoming data and writes it to the output pipe
	    SortFilter sort2 = new SortFilter();	//Filter that sorts the incoming data and writes it to the output pipe
	    MergeFilter merge = new MergeFilter();  //Filter that merges two incoming streams of sorted data 
	    										//       into one sorted output stream
	    
	    SplitterFilter splitter1 = new SplitterFilter();	//Filter that splits a stream of data into two
	    
	    PressureWPFilter pressureWP = new PressureWPFilter(90, 45); //Filter that cleans pressure data by extrapolating wild points
	    SuperSinkFilter superSink1 = new SuperSinkFilter(
				new int[]{},
				new int[]{0,3},								//First sink that is parametrized to write wild point values
				null, "WildpointsC_1.dat", -1); 
	    
	    SplitterFilter splitter2 = new SplitterFilter();	//Filter that splits a stream of data into two
	    SplitterFilter splitter3 = new SplitterFilter();	//Filter that splits a stream of data into two
	    AttitudeWPFilter attitude = new AttitudeWPFilter();
	    SuperSinkFilter superSink2 = new SuperSinkFilter(
				new int[]{0,1,2,3,4,5},						//second sink that is parametrized to write clean data to one file 
				new int[]{0,5,3},							// and wild point data to another file
				"OutputC.dat", "WildpointsC_2.dat", -1);
	    
	    
		   /****************************************************************************
		   * Here we connect the filters of System C
		   ****************************************************************************/	    
	    
	   sort1.Connect(source1, 0, 0);		//connects the output of the source filter to a sort filter
	   sort2.Connect(source2, 0, 0);		//connects the output of the second source filter to a sort filter
	   merge.Connect(sort1, 0, 0);			//connects the output of a sort filter to the first input of a merge filter
	   merge.Connect(sort2, 1, 0);			//connects the output of a sort filter to the second input of the merge filter
	   splitter1.Connect(merge, 0, 0);		//connects the output of the merge filter to the input of the splitter
	   pressureWP.Connect(splitter1, 0, 0);	//connects the first output of the splitter to the pressure wild point filter
	   
	   splitter2.Connect(pressureWP, 0, 0); //connects the output of the pressure wild point filter to the input of a splitter
	   superSink1.Connect(splitter2, 0, 0); //connects the first output of splitter2 to the first input of the supersink1
	   superSink1.Connect(splitter1, 1, 1); //connects the second output of splitter1 to second input of superSink 1
	   
	   splitter3.Connect(splitter2,0,1);	//connects second output of splitter2 to the input of splitter3
	   attitude.Connect(splitter3,0,0);		//connects first output of splitter3 to the attitude filter
	   superSink2.Connect(attitude, 0, 0);	//connects output of attitude filter to first input of superSink2
	   superSink2.Connect(splitter3, 1, 1); //connects second output of splitter3 to the second input of superSink2
	   
	   /****************************************************************************
	   * Here we start the threads required for System C
	   ****************************************************************************/		   
	   
	   source1.start();
	   source2.start();
	   sort1.start();
	   sort2.start();
	   
	   merge.start();
	   splitter1.start();
	   pressureWP.start();
	   superSink1.start();
	   
	   splitter2.start();
	   splitter3.start();
	   attitude.start();
	   superSink2.start();
   } // main

} // System C